package cn.tannn.cat.file.sdk.utils;

import cn.tannn.cat.file.sdk.constants.ContentTypeConstants;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * Byte -> MultipartFile
 */
public class ByteMultipartFile implements MultipartFile {

    /**
     * 文件名
     */
    private final String name;
    /**
     * 原始文件名
     */
    private final String originalFilename;
    /**
     * "application/json"
     * @see ContentTypeConstants
     */
    private final String contentType;

    /**
     * 文件流
     */
    private final byte[] content;

    /**
     * 创建一个带有最少参数的字节文件上传对象
     *
     * @param name 文件名（不能为空）
     * @param content 文件流（可以为空，视为为空字符串）
     */
    public ByteMultipartFile(@NonNull String name, @Nullable byte[] content) {
        this(name, "", null, content);
    }

    /**
     * Creates a ByteMultipartFile from an InputStream
     *
     * @param name 文件名（不能为空）
     * @param contentStream 文件流（不能为 null）
     * @throws IOException if reading from the stream fails
     */
    public ByteMultipartFile(@NonNull String name, @NonNull InputStream contentStream) throws IOException {
        this(name, "", null, contentStream);
    }

    /**
     * 创建一个包含所有参数的 ByteMultipartFile 对象
     *
     * @param name 文件名（不能为空）
     * @param originalFilename 原始文件名（可以为空或为空字符串）
     * @param contentType  contentType（可以为空）
     * @param content  文件流（可以为空，视为为空字符串）
     */
    public ByteMultipartFile(@NonNull String name,
                            @Nullable String originalFilename,
                            @Nullable String contentType,
                            @Nullable byte[] content) {
        Assert.hasLength(name, "Name must not be empty");

        this.name = name;
        this.originalFilename = originalFilename != null ? originalFilename : "";
        this.contentType = contentType;
        // Defensive copy to prevent external modification
        this.content = content != null ? Arrays.copyOf(content, content.length) : new byte[0];
    }

    /**
     * 根据输入流创建一个带有所有参数的字节文件上传对象
     *
     * @param name 文件名（不能为空）
     * @param originalFilename 原始文件名（可以为空或为空字符串）
     * @param contentType contentType（可以为空）
     * @param contentStream 文件流（不能为 null）
     * @throws IOException if reading from the stream fails
     */
    public ByteMultipartFile(@NonNull String name,
                            @Nullable String originalFilename,
                            @Nullable String contentType,
                            @NonNull InputStream contentStream) throws IOException {
        Assert.notNull(contentStream, "Content stream must not be null");
        this.name = name;
        this.originalFilename = originalFilename != null ? originalFilename : "";
        this.contentType = contentType;
        this.content = FileCopyUtils.copyToByteArray(contentStream);
    }

    @Override
    @NonNull
    public String getName() {
        return this.name;
    }

    @Override
    @NonNull
    public String getOriginalFilename() {
        return this.originalFilename;
    }

    @Override
    @Nullable
    public String getContentType() {
        return this.contentType;
    }

    @Override
    public boolean isEmpty() {
        return this.content.length == 0;
    }

    @Override
    public long getSize() {
        return this.content.length;
    }

    @Override
    @NonNull
    public byte[] getBytes() throws IOException {
        // Return defensive copy to prevent external modification
        return Arrays.copyOf(this.content, this.content.length);
    }

    @Override
    @NonNull
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(this.content);
    }

    @Override
    public void transferTo(@NonNull File dest) throws IOException, IllegalStateException {
        Assert.notNull(dest, "Destination file must not be null");
        FileCopyUtils.copy(this.content, dest);
    }

    @Override
    public String toString() {
        return "ByteMultipartFile[name='" + this.name +
               "', originalFilename='" + this.originalFilename +
               "', contentType='" + this.contentType +
               "', size=" + this.content.length + "]";
    }
}
